package controllers

import config.{Global, MyAwait, MyFile, MyRow, MyString}
import play.api.data.Form
import play.api.data.Forms._
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ControllerComponents}
import utils.{ReadExcel, TableUtils}

import javax.inject.Inject
import scala.concurrent.ExecutionContext
import scala.math.log10

class ProteomicsController @Inject()(cc: ControllerComponents)
                                    (implicit exec: ExecutionContext) extends AbstractController(cc) with MyRow with MyAwait with MyString with MyFile {

  def proteomicsPage = Action { implicit request =>
    Ok(views.html.proteomics.proteomicsPage())
  }

  def proteomics2Page = Action { implicit request =>
    Ok(views.html.proteomics.proteomics2Page())
  }

  def proteomics3Page = Action { implicit request =>
    Ok(views.html.proteomics.proteomics3Page())
  }

  def getTypeHead = Action { implicit request =>
    Ok(Json.obj("geneid" -> TableUtils.proteomicsGeneId, "protein" -> TableUtils.proteomicsProtein,
      "geneName" -> TableUtils.proteomicsGeneName))
  }

  case class ExprData(ids: String)

  val ExprForm = Form(
    mapping(
      "ids" -> text
    )(ExprData.apply)(ExprData.unapply)
  )

  def getGeneExprData(formId: String) = Action { implicit request =>
    val ids = ExprForm.bindFromRequest.get.ids.trim.split(",").map(_.trim).toSeq

    val rna = formId match {
      case "geneIdForm" =>
        TableUtils.proteomics.filter(x => ids.indexOf(x.head) != -1)
      case "proteinForm" =>
        TableUtils.proteomics.filter(x => ids.indexOf(x(1)) != -1)
      case "geneNameForm" =>
        TableUtils.proteomics.filter(x => ids.indexOf(x(2)) != -1)
    }


    val table = rna.map { x => x.zipWithIndex.map { y => y._2.toString -> y._1 }.toMap }

    val header = TableUtils.proteomicsHeader

    val heatmap = {
      val data = "GeneID,mRNA,EXP\n" + rna.zipWithIndex.flatMap { x =>
        x._1.slice(13, 19).zipWithIndex.map { y =>
          y._2 + "," + x._2 + "," + log2(y._1.toDouble)
        }
      }.mkString("\n")
      val xAxis = header.slice(13, 19)
      val yAxis = rna.map(_.head)
      Json.obj("xAxis" -> xAxis, "yAxis" -> yAxis, "csv" -> data)
    }

    val line = {
      val data = rna.map { x =>
        Json.obj("name" -> x.head, "data" -> x.slice(13, 19).map(_.toDouble))
      }
      val xAxis = header.slice(13, 19)

      Json.obj("xAxis" -> xAxis, "series" -> data)

    }

    Ok(Json.obj("table" -> table, "header" -> header, "heatmap" -> heatmap, "line" -> line))
  }

  def log2(x: Double): Double = log10(x + 1) / log10(2.0)


  def getDiffData = Action { implicit request =>
    val lines = s"${Global.path}/config/proteimics2.txt".readLines.map(_.split("\t"))
    val header = lines.head
    val data = lines.tail.map { x =>
      x.zipWithIndex.map { y =>
        y._2.toString -> y._1
      }.toMap
    }.toSeq
    Ok(Json.obj("header" -> header, "data" -> data))
  }

  def getProteinName = Action { implicit request =>
    val name = s"${Global.path}/protein".listFile.map(_.getName.split('.').init.mkString("."))
    Ok(Json.toJson(name))
  }

  def getByName(name: String) = Action { implicit request =>
    val n = if (name == "Medicago sativa L. cv. Ladak , inoculated nodule and NaCltreatment") {
      "Medicago sativa L. cv. Ladak+, inoculated nodule and NaCltreatment"
    } else if(name == "Medicago sativa L. cv. Ladak ,）和根瘤菌（根瘤菌Dormal 菌株"){
      "Medicago sativa L. cv. Ladak+,）和根瘤菌（根瘤菌Dormal 菌株"
    } else {
      name
    }

    val lines = ReadExcel.xlsx2Lines(s"${Global.path}/protein/$n.xlsx".toFile).map(_.split("\t"))
    val header = lines.head.map(x => if (x == "NA") "" else x)
    val table = lines.tail.zipWithIndex.map{case (x,i) => x.zipWithIndex.map { y => y._2.toString -> y._1 }.toMap ++ Map("linesNum" -> i.toString)}

    Ok(Json.obj("table" -> table, "header" -> header))


  }


  def getHeatmapPlotData(name: String, selected: String ) = Action { implicit request =>
    val n = if (name == "Medicago sativa L. cv. Ladak , inoculated nodule and NaCltreatment") {
      "Medicago sativa L. cv. Ladak+, inoculated nodule and NaCltreatment"
    } else if (name == "Medicago sativa L. cv. Ladak ,）和根瘤菌（根瘤菌Dormal 菌株") {
      "Medicago sativa L. cv. Ladak+,）和根瘤菌（根瘤菌Dormal 菌株"
    } else {
      name
    }


    val lines = ReadExcel.xlsx2Lines(s"${Global.path}/protein/$n.xlsx".toFile).map(_.split("\t"))
    val header = lines.head.map(x => if (x == "NA") "" else x)

    val (min, max,proId) = name match {
      case "Alfalfa Nongjing No.1, NaCl treatment" => (9, 22,1)
      case "Alfalfa Zhongmu No.1_Medicago truncatula R108,alkali treatment" => (7, 19,1)
      case "Alfalfa, different growth stages(sprout, early-flowering and Mid-flowering)" => (2, 13,0)
      case "M25, Waterlogging treatment" => (2, 12,0)
      case "Medicago sativa L. cv. Kangsai, selenium treatment" => (6, 16,1)

      case "Medicago sativa L. cv. Ladak , inoculated nodule and NaCltreatment" => (5, 9,0)
      case "Medicago sativa L. cv. Ladak ,）和根瘤菌（根瘤菌Dormal 菌株" => (4, 7,1)


      case "Medicago sativa L. Victoria, CdCl treatment" => (2, 22,0)
      case "Medicago truncatula A17, Drought and rewater treatment" => (1, 6,0)

      case "Medicago truncatula A17, inoculated nodule and drought treatment(mannitol)" => (2, 50,0)
      case "Medicago truncatula Jemalong A17，NaCl treatment, leaf" => (2, 17,1)
      case "Medicago truncatula R108, salt treatment" => (7, 19,1)
      case "蛋白组_Se_Kangsai" => (5, 13,1)
    }
    val yAxis = header.slice(min, max)

    val selectArray = selected.split(",").map(_.toInt)
    val selectLines = selectArray.map{x=>
      lines.tail(x)
    }

    val heatmap = {
      val data = "GeneID,mRNA,EXP\n" + selectLines.zipWithIndex.flatMap { x =>
        x._1.slice(min, max).zipWithIndex.map { y =>
          if(y._1 == "NA" || y._1.trim == "" || y._1.trim == "-"){
            x._2 + "," + y._2 + ",0"
          }else{
            x._2 + "," + y._2 + "," + log2(y._1.toDouble)
          }
        }
      }.mkString("\n")
      val xAxis = lines.tail.map(_(proId))

      Json.obj("xAxis" -> xAxis, "csv" -> data, "yAxis" -> yAxis, "title" -> name)
    }

    val line = {
      val data = selectLines.map { x =>
        Json.obj("name" -> x(proId), "data" -> x.slice(min, max).map{y=>
          if (y == "NA" || y.trim == "" || y.trim == "-") {
           0
          } else {
            y.toDouble
          }

        })
      }
      val xAxis = header.slice(min, max)

      Json.obj("xAxis" -> xAxis, "series" -> data, "title" -> name)

    }

    Ok(Json.obj("heatmap" -> heatmap,"line" -> line))

  }


}
